# coding: UTF-8
# -*- coding: UTF-8 -*-
import threading
from threading import Thread
import struct
import time
import hashlib
import base64
import socket
import types
import multiprocessing
import os
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import random
from os.path import join as pjoin
import json
import inspect
import ctypes


"""
发送验证码邮件，并且将数据写入json以供前端查询
"""





#关闭线程
def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")



def ranstr(num):
    # 猜猜变量名为啥叫 H
    H = 'abcdefghijklmnopqrstuvwxyz0123456789'
    salt = ''
    for i in range(num):
        salt += random.choice(H)
    return salt


#循环定时执行

timeleft = 0
# 真正要执行的函数
def counttime():
    global timeleft
    timeleft =timeleft-1
# 每隔1秒钟执行
def ReRunFuc():
    while (timeleft != 0):
        counttime()
        time.sleep(1)
        #print(threading.currentThread().name)
        #print(threading.currentThread().ident)
    print("thread closed")
    #writeJson('UserID', 'UserEmail', 'UserIP')
    _async_raise(threading.currentThread().ident, SystemExit)


def reCount():
    print("reCUONTing")
    global timeleft
    timeleft = 300
    #t4.join()
    t4 = threading.Thread(target=ReRunFuc)
    t4.start()

mode = "initialize"
pic_size = 0
pic_receive = 0
pic = ""
pic_repeat = []
receiveddata = ''
IDnum = 1001
class returnCrossDomain(Thread):



    def __init__(self, connection):
        Thread.__init__(self)
        self.con = connection
        self.isHandleShake = False
    def run(self):
        global mode
        global pic_size
        global pic_receive
        global pic
        global pic_repeat
        global receiveddata
        global IDnum
        while True:
            if not self.isHandleShake:
                # 开始握手阶段
                header = self.analyzeReq()
                secKey = header['Sec-WebSocket-Key'];
                acceptKey = self.generateAcceptKey(secKey)
                response = "HTTP/1.1 101 Switching Protocols\r\n"
                response += "Upgrade: websocket\r\n"
                response += "Connection: Upgrade\r\n"
                response += "Sec-WebSocket-Accept: %s\r\n\r\n" % (acceptKey.decode('utf-8'))
                self.con.send(response.encode())
                self.isHandleShake = True
                if (mode == "initialize"):
                    mode = "get_order"
                print('response:' + response[75:127])
                # 握手阶段结束
                # 读取命令阶段
            elif mode == "get_order":
                opcode = self.getOpcode()
                if opcode == 8:
                    self.con.close()
                self.getDataLength()
                clientData = self.readClientData()
                print('客户端数据：' + str(clientData))

                if(timeleft == 0):
                    print("timeleft == 0")
                    # 处理数据
                    result = str(clientData)  # ''.join(data)
                    detail = result.split(',', -1)
                    IDnum = IDnum + 1
                    UserID0 = str(IDnum)
                    UserEmail0 = str(detail[0])
                    UserIP0 = str(detail[1])
                    print("UserID   :" + UserID0+"  UserEmail    :" + UserEmail0+"  UserIP   :" + UserIP0)

                    if(1):
                        os.system("python SendEmail.py "+UserID0+" "+UserEmail0+" "+ UserIP0)
                        reCount()
                    receiveddata = str(clientData)
                    ans = self.answer(clientData)
                    self.sendDataToClient(ans)

                else:
                    print("计时ing")

                    # 处理数据
                    ttt =str(timeleft)
                    ans = str('waiting for '+ttt+' seconds')
                    print('timeleft:' + str(timeleft))
                    self.sendDataToClient(ans)


                # 处理数据
    def legal(self, string):  # python总会胡乱接收一些数据。。只好过滤掉
        if len(string) == 0:
            return 0
        elif len(string) <= 100:
            if self.loc(string) != len(string):
                return 0
            else:
                if mode != "get_pic":
                    return 1
                elif len(string) + pic_receive == pic_size:
                    return 1
                else:
                    return 0
        else:
            if self.loc(string) > 100:
                if mode != "get_pic":
                    return 1
                elif string[0:100] not in pic_repeat:
                    pic_repeat.append(string[0:100])
                    return 1
                else:
                    return -1  # 收到重复数据，需要重定位
            else:
                return 0
    def loc(self, string):
        i = 0
        while (i < len(string) and self.rightbase64(string[i])):
            i = i + 1
        return i
    def rightbase64(self, ch):
        if (ch >= "a") and (ch <= "z"):
            return 1
        elif (ch >= "A") and (ch <= "Z"):
            return 1
        elif (ch >= "0") and (ch <= "9"):
            return 1
        elif ch == '+' or ch == '/' or ch == '|' or ch == '=' or ch == ' ' or ch == "'" or ch == '!' or ch == ':':
            return 1
        else:
            return 0
    def analyzeReq(self):
        reqData = self.con.recv(1024).decode()
        reqList = reqData.split('\r\n')
        headers = {}
        for reqItem in reqList:
            if ': ' in reqItem:
                unit = reqItem.split(': ')
                headers[unit[0]] = unit[1]
        return headers
    def generateAcceptKey(self, secKey):
        sha1 = hashlib.sha1()
        sha1.update((secKey + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11').encode())
        sha1_result = sha1.digest()
        acceptKey = base64.b64encode(sha1_result)
        return acceptKey
    def getOpcode(self):
        first8Bit = self.con.recv(1)
        first8Bit = struct.unpack('B', first8Bit)[0]
        opcode = first8Bit & 0b00001111
        return opcode
    def getDataLength(self):
        second8Bit = self.con.recv(1)
        second8Bit = struct.unpack('B', second8Bit)[0]
        masking = second8Bit >> 7
        dataLength = second8Bit & 0b01111111
        # print("dataLength:",dataLength)
        if dataLength <= 125:
            payDataLength = dataLength
        elif dataLength == 126:
            payDataLength = struct.unpack('H', self.con.recv(2))[0]
        elif dataLength == 127:
            payDataLength = struct.unpack('Q', self.con.recv(8))[0]
        self.masking = masking
        self.payDataLength = payDataLength
        # print("payDataLength:", payDataLength)

    def readClientData(self):
        if self.masking == 1:
            maskingKey = self.con.recv(4)
        data = self.con.recv(self.payDataLength)
        if self.masking == 1:
            i = 0
            trueData = ''
            for d in data:
                trueData += chr(d ^ maskingKey[i % 4])
                i += 1
            return trueData
        else:
            return data
    def sendDataToClient(self, text):
        sendData = ''
        sendData = struct.pack('!B', 0x81)
        length = len(text)
        if length <= 125:
            sendData += struct.pack('!B', length)
        elif length <= 65536:
            sendData += struct.pack('!B', 126)
            sendData += struct.pack('!H', length)
        elif length == 127:
            sendData += struct.pack('!B', 127)
            sendData += struct.pack('!Q', length)
        sendData += struct.pack('!%ds' % (length), text.encode())
        dataSize = self.con.send(sendData)

    def answer(self, data):

        if ('@' in data) :
            return 'EmailAdress Accepted!\r\n'
        else:
            return data



    def padding(self, data):
        missing_padding = 4 - len(data) % 4
        if missing_padding:
            data += '=' * missing_padding
        return data


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 9999))
    print("监听端口：9999")
    sock.listen(5)
    while True:
        try:
            connection, address = sock.accept()
            returnCrossDomain(connection).start()
        except:
            time.sleep(1)
            print("error")

if __name__ == "__main__":
    # 此处写你主线程要处理的事情.....
    main()
    # 此处写你主线程要处理的事情.....



